package com.xadrez.view;

import com.xadrez.ia.IA;
import com.xadrez.modelo.Bispo;
import com.xadrez.modelo.Cavalo;
import com.xadrez.modelo.Peao;
import com.xadrez.modelo.Peca;
import com.xadrez.modelo.Posicao;
import com.xadrez.modelo.Rainha;
import com.xadrez.modelo.Rei;
import com.xadrez.modelo.Torre;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.event.MouseEvent;
import javax.swing.JLabel;

public class Pintor {

    // <editor-fold defaultstate="collapsed" desc="MÉTODOS GERAIS">
    //Pinta quadradros referentes aos movimentos possíveis de uma peça
    public static void pintaQuadrados(MouseEvent e, PecaView pecaView) {

        limpaTabuleiro();
        TabuleiroView tabuleiro = TabuleiroView.getInstance();
        Peca peca = pecaView.getPeca();

        if (!(peca.getJogador() instanceof IA)) {
            // RECUPERA LOCALIZACAO
            Component componentTemp = tabuleiro.findComponentAt(e.getX(), e.getY());
            int x = Mouse.getX(componentTemp);
            int y = Mouse.getY(componentTemp);

            //PINTA POSICAO ATUAL
            Container parent = componentTemp.getParent();
            parent.setBackground(Cor.getInstance().getCorPecaJogador());

            if (peca instanceof Torre) {
                pintaQuadradosHorizontais(x, y);
                pintaQuadradosVerticais(x, y);
            } else if (peca instanceof Bispo) {
                pintaQuadradosDiagonais(x, y);
            } else if (peca instanceof Rainha) {
                pintaQuadradosHorizontais(x, y);
                pintaQuadradosVerticais(x, y);
                pintaQuadradosDiagonais(x, y);
            } else if (peca instanceof Peao) {
                pintaQuadradosPeao(((Peao) peca).isPrimeiroMovimento(), x, y);
            } else if (peca instanceof Cavalo) {
                pintaQuadradosCavalo(x, y);
            } else if (peca instanceof Rei) {
                pintaQuadradosRei(x, y);
            }
        }
    }

    //Pinta quadradros referentes aos movimentos possíveis de uma peça
    private static void pinta(int x, int y) {
        Component c = TabuleiroView.getInstance().findComponentAt(x, y);
        PecaView pecaView = TabuleiroView.getInstance().buscaPeca(x, y);

        if (pecaView != null) {
            Container parent = c.getParent();
            if (pecaView.getPeca().getJogador() instanceof IA) {
                parent.setBackground(Cor.getInstance().getCorPecaInimigo());
            }
        } else {
            if (c != null) {
                Container parent = (Container) c;
                parent.setBackground(Cor.getInstance().getCorCampoLivre());
            }
        }
    }

    //Repinta o tabuleiro com as cores iniciais, limpando desenhos de movimento.
    public static void limpaTabuleiro() {
        for (int i = 0; i < 64; i++) {
            Component c = TabuleiroView.getInstance().getComponent(i);

            int row = (i / 8) % 2;
            if (row == 0) {
                if (c instanceof JLabel) {
                    Container parent = c.getParent();
                    parent.setBackground(i % 2 == 0 ? Cor.getInstance().getCorTabuleiro() : Color.white);
                } else {
                    Container parent = (Container) c;
                    parent.setBackground(i % 2 == 0 ? Cor.getInstance().getCorTabuleiro() : Color.white);
                }
            } else {
                if (c instanceof JLabel) {
                    Container parent = c.getParent();
                    parent.setBackground(i % 2 == 0 ? Color.white : Cor.getInstance().getCorTabuleiro());
                } else {
                    Container parent = (Container) c;
                    parent.setBackground(i % 2 == 0 ? Color.white : Cor.getInstance().getCorTabuleiro());
                }
            }
        }
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="MÉTODOS QUE PINTAM QUADRADOS VERTICAIS/HORIZONTAIS">
    //---------------------------------------------------------------------------------------------------------------
    //Pinta sequencia de quadrados até achar uma peça no caminho
    private static void pintaQuadradosHorizontais(int x, int y) {
        Pintor.pintaQuadradosDaDireita(x, y);
        Pintor.pintaQuadradosDaEsquerda(x, y);
    }

    private static void pintaQuadradosDaDireita(int x, int y) {
        TabuleiroView tabuleiro = TabuleiroView.getInstance();

        boolean pinta = true;
        x = x + tabuleiro.TAMANHOQUADRADO;
        while (pinta && x < tabuleiro.TAMANHOTABULEIRO) {
            if (!tabuleiro.temPecaDoJogadorNaPosicao(x, y)) {
                if (tabuleiro.temAdversarioNaPosicao(x, y)) {
                    pinta = false;
                }
                pinta(x, y);
                x = x + tabuleiro.TAMANHOQUADRADO;
            } else {
                pinta = false;
            }
        }
    }

    private static void pintaQuadradosDaEsquerda(int x, int y) {
        TabuleiroView tabuleiro = TabuleiroView.getInstance();

        boolean pinta = true;
        x = x - tabuleiro.TAMANHOQUADRADO;
        while (pinta && x >= 0) {
            if (!tabuleiro.temPecaDoJogadorNaPosicao(x, y)) {
                if (tabuleiro.temAdversarioNaPosicao(x, y)) {
                    pinta = false;
                }
                pinta(x, y);
                x = x - tabuleiro.TAMANHOQUADRADO;
            } else {
                pinta = false;
            }
        }
    }

    //---------------------------------------------------------------------------------------------------------------
    //Pinta sequencia de quadrados até achar uma peça no caminho
    private static void pintaQuadradosVerticais(int x, int y) {
        Pintor.pintaQuadradosDeCima(x, y);
        Pintor.pintaQuadradosDeBaixo(x, y);
    }

    private static void pintaQuadradosDeCima(int x, int y) {
        TabuleiroView tabuleiro = TabuleiroView.getInstance();

        boolean pinta = true;
        y = y + tabuleiro.TAMANHOQUADRADO;
        while (pinta && y < tabuleiro.TAMANHOTABULEIRO) {
            if (!tabuleiro.temPecaDoJogadorNaPosicao(x, y)) {
                if (tabuleiro.temAdversarioNaPosicao(x, y)) {
                    pinta = false;
                }
                pinta(x, y);
                y = y + tabuleiro.TAMANHOQUADRADO;
            } else {
                pinta = false;
            }
        }
    }

    private static void pintaQuadradosDeBaixo(int x, int y) {
        TabuleiroView tabuleiro = TabuleiroView.getInstance();

        boolean pinta = true;
        y = y - tabuleiro.TAMANHOQUADRADO;
        while (pinta && y >= 0) {
            if (!tabuleiro.temPecaDoJogadorNaPosicao(x, y)) {
                if (tabuleiro.temAdversarioNaPosicao(x, y)) {
                    pinta = false;
                }
                pinta(x, y);
                y = y - tabuleiro.TAMANHOQUADRADO;
            } else {
                pinta = false;
            }
        }
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="MÉTODOS QUE PINTAM QUADRADOS DIAGONAIS">
    //Pinta sequencia de quadrados até achar uma peça no caminho
    private static void pintaQuadradosDiagonais(int x, int y) {
        pintaQuadradosNordeste(x, y);
        pintaQuadradosNoroeste(x, y);
        pintaQuadradosSudeste(x, y);
        pintaQuadradosSudoeste(x, y);
    }

    private static void pintaQuadradosNordeste(int x, int y) {

        TabuleiroView tabuleiro = TabuleiroView.getInstance();

        boolean pinta = true;
        x = x + tabuleiro.TAMANHOQUADRADO;
        y = y - tabuleiro.TAMANHOQUADRADO;
        while (pinta && x < tabuleiro.TAMANHOTABULEIRO && y >= 0) {
            if (!tabuleiro.temPecaDoJogadorNaPosicao(x, y)) {
                if (tabuleiro.temAdversarioNaPosicao(x, y)) {
                    pinta = false;
                }
                pinta(x, y);
                x = x + tabuleiro.TAMANHOQUADRADO;
                y = y - tabuleiro.TAMANHOQUADRADO;
            } else {
                pinta = false;
            }
        }

    }

    private static void pintaQuadradosNoroeste(int x, int y) {

        TabuleiroView tabuleiro = TabuleiroView.getInstance();

        boolean pinta = true;
        x = x - tabuleiro.TAMANHOQUADRADO;
        y = y - tabuleiro.TAMANHOQUADRADO;
        while (pinta && x >= 0 && y >= 0) {
            if (!tabuleiro.temPecaDoJogadorNaPosicao(x, y)) {
                if (tabuleiro.temAdversarioNaPosicao(x, y)) {
                    pinta = false;
                }
                pinta(x, y);
                x = x - tabuleiro.TAMANHOQUADRADO;
                y = y - tabuleiro.TAMANHOQUADRADO;
            } else {
                pinta = false;
            }
        }
    }

    private static void pintaQuadradosSudeste(int x, int y) {

        TabuleiroView tabuleiro = TabuleiroView.getInstance();

        boolean pinta = true;
        x = x + tabuleiro.TAMANHOQUADRADO;
        y = y + tabuleiro.TAMANHOQUADRADO;
        while (pinta && x < tabuleiro.TAMANHOTABULEIRO && y < tabuleiro.TAMANHOTABULEIRO) {
            if (!tabuleiro.temPecaDoJogadorNaPosicao(x, y)) {
                if (tabuleiro.temAdversarioNaPosicao(x, y)) {
                    pinta = false;
                }
                pinta(x, y);
                x = x + tabuleiro.TAMANHOQUADRADO;
                y = y + tabuleiro.TAMANHOQUADRADO;
            } else {
                pinta = false;
            }
        }
    }

    private static void pintaQuadradosSudoeste(int x, int y) {

        TabuleiroView tabuleiro = TabuleiroView.getInstance();

        boolean pinta = true;
        x = x - tabuleiro.TAMANHOQUADRADO;
        y = y + tabuleiro.TAMANHOQUADRADO;
        while (pinta && x >= 0 && y < tabuleiro.TAMANHOTABULEIRO) {
            if (!tabuleiro.temPecaDoJogadorNaPosicao(x, y)) {
                if (tabuleiro.temAdversarioNaPosicao(x, y)) {
                    pinta = false;
                }
                pinta(x, y);
                x = x - tabuleiro.TAMANHOQUADRADO;
                y = y + tabuleiro.TAMANHOQUADRADO;
            } else {
                pinta = false;
            }
        }

    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="MÉTODOS QUE PINTAM QUADRADOS PARA PECAS ESPECIFICAS">
    private static void pintaQuadradosPeao(boolean primeiroMovimento, int x, int y) {

        TabuleiroView tabuleiro = TabuleiroView.getInstance();
        int tamanho = tabuleiro.TAMANHOQUADRADO;

        if (primeiroMovimento) {
            pinta(x, y - tamanho);
            pinta(x, y - tamanho * 2);

            primeiroMovimento = false;
        } else {
            if (isQuadradoDentroDosLimites(new Posicao(x,y - tamanho)) 
                    && !tabuleiro.temAdversarioNaPosicao(x, y - tamanho)) {
                pinta(x, y - tamanho);
            }

            if (isQuadradoDentroDosLimites(new Posicao(x + tamanho, y - tamanho))
                    && tabuleiro.temAdversarioNaPosicao(x + tamanho, y - tamanho)) {
                pinta(x + tamanho, y - tamanho);
            }
            if (isQuadradoDentroDosLimites(new Posicao(x - tamanho, y - tamanho))
                    && tabuleiro.temAdversarioNaPosicao(x - tamanho, y - tamanho)) {
                pinta(x - tamanho, y - tamanho);
            }
        }
    }

    private static void pintaQuadradosCavalo(int x, int y) {
        int tamanho = TabuleiroView.getInstance().TAMANHOQUADRADO;

        //VERTICAL
        pinta(x + tamanho, y - tamanho * 2);
        pinta(x - tamanho, y - tamanho * 2);
        pinta(x + tamanho, y + tamanho * 2);
        pinta(x - tamanho, y + tamanho * 2);

        //HORIZONTAL
        pinta(x + tamanho * 2, y + tamanho);
        pinta(x + tamanho * 2, y - tamanho);
        pinta(x - tamanho * 2, y + tamanho);
        pinta(x - tamanho * 2, y - tamanho);
    }

    private static void pintaQuadradosRei(int x, int y) {
        int tamanho = TabuleiroView.getInstance().TAMANHOQUADRADO;

        //VERTICAL
        pinta(x, y - tamanho);
        pinta(x, y + tamanho);

        //HORIZONTAL
        pinta(x + tamanho, y);
        pinta(x - tamanho, y);

        //DIAGONAL
        pinta(x - tamanho, y - tamanho);
        pinta(x + tamanho, y - tamanho);
        pinta(x - tamanho, y + tamanho);
        pinta(x + tamanho, y + tamanho);
    }
    // </editor-fold>

    private static boolean isQuadradoDentroDosLimites(Posicao posicao) {
        boolean confirma = false;
        if (posicao.getX() < TabuleiroView.getInstance().TAMANHOTABULEIRO 
                && posicao.getX() >= 0 
                && posicao.getY() < TabuleiroView.getInstance().TAMANHOTABULEIRO 
                && posicao.getY() >= 0) {
            confirma = true;
        }
        return confirma;
    }
}
